home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / pdisk.zip / PART.C < prev    next >
C/C++ Source or Header  |  1989-01-12  |  14KB  |  491 lines

  1. /* program to manipulate partitions on a fixed disk.
  2.  * Written by Scott E. Garfinkle, July 1986.  All rights reserved.
  3.  *
  4.  * This program will examine the partition table of a fixed disk.  It will
  5.  * probably only run under a close PC XT or AT compatible running PC-DOS.
  6.  *
  7.  * usage: part [drive_number]
  8.  *  where drive_number can be either 1 or 2.  Default is 1.
  9. */
  10. #include "part.h"
  11. #include <errno.h>
  12. #include <ctype.h>
  13.  
  14. #define ESC 27
  15.  
  16. extern BOOT *master_boot_rec,    /* master boot record of currently selected disk */
  17.             *part_boot_rec[4];    /* boot record of each (active) logical partition */
  18. extern DISK_TABLE far * fd_tbl;
  19. extern PARTDATA part_data[4];
  20. extern byte fixed_disk,    /* BIOS "address" of currently selected fixed disk */
  21.             num_disks;    /* number of drives attached to controller */
  22. word sector_size;    /* aka bytes per sector */
  23. word lineno;    /* current screen line */
  24.  
  25. /* 16x16 bit unsigned multiply w/32 bit result */
  26. extern dword umul1632(word,word);
  27.  
  28. char *version="Part v2.01 11 Jan 89";
  29. /* 2.01 -- allowed creating non-DOS partitions without formatting.
  30.  */
  31.  
  32. main(argc,argv)
  33. int argc;
  34. char **argv;
  35. {
  36.     int i, c;
  37.  
  38.     if(argc > 2 || (argc>1 && argv[1][0] != '0' && argv[1][0] != '1')) {
  39.         fprintf(stderr,"Usage: part [0|1]\n");
  40.         exit(-1);
  41.         /* NOTREACHED */
  42.     }
  43.     fixed_disk = argc==1 ? DISK0 : (argv[1][0] == '0' ? DISK0 : DISK1);
  44.     erase_eos(0);
  45.     scr_pos(22,0);
  46.     printf("Partition table editor, Copyright(C) 1986, 1988 S. E. Garfinkle.");
  47.     scr_pos(23,0);
  48.     printf("All rights reserved.");
  49.     do {
  50.         sector_size = get_scr_val(14,"Enter sector size (256,512,1024,etc.):",512,256,16*1024);
  51.     } while (sector_size != 256 && (sector_size & 0x1ff));
  52.     init();    /* Will exit from init if no disks are attached */
  53.     while(1) {
  54.         scr_pos(3,0);
  55.         erase_eos(0);
  56.         pr_head();
  57.         for(i=0; i<4; i++)
  58.             if(part_data[i].sys_ind)
  59.                 pr_part(i+1,master_boot_rec->ptable+i);
  60.             else
  61.                 printf("%d  Not active\n",i+1);
  62.         lineno = (scr_rpos() >> 8) + 1;
  63.         scr_pos(lineno+1,0);
  64.         puts("         1. Add Partition");
  65.         puts("         2. Change Partition");
  66.         puts("         3. Delete Partition");
  67.         puts("         4. Change Current Disk Parameters");
  68.         if(num_disks>1) {
  69.             i = '5';
  70.             puts("         5. Switch Drive");
  71.         }
  72.         else
  73.             i = '4';
  74.         c=(int) get_scr_char(lineno,"Select:  0. Exit            ",'0',i);
  75.         lineno += i-'0';
  76.         switch(c) {
  77.         case '.':
  78.         case '0':
  79.             clean_quit();
  80.             /* NOTREACHED */
  81.         case '1':
  82.             add_part();
  83.             break;
  84.         case '2':
  85.             mod_part();
  86.             break;
  87.         case '3':
  88.             del_part();
  89.             break;
  90.         case '4':
  91.             change_parms();
  92.             break;
  93.         case '5':
  94.             do {
  95.                 sector_size = get_scr_val(14,"Enter sector size (256,512,1024,etc.):",512,256,16*1024);
  96.             } while (sector_size != 256 && (sector_size & 0x1ff));
  97.             fixed_disk = fixed_disk==DISK0 ? DISK1 : DISK0;
  98.             init();
  99.             break;
  100.         }
  101.     }
  102.     /* NOTREACHED */
  103. }
  104.  
  105. void
  106. add_part()
  107. {
  108.     int i, j, k, save_line, partno, sysno, fat_size, flag, bootable;
  109.     word start, end, minstart, maxend, temp, fats_in_sector;
  110.     word uns, nsects, nheads, maxcyls, csize;
  111.     PARTITION *part;
  112.     BPB *bptr;
  113.     extern word bcode_len, _shprod;
  114.     extern char boot_code[];
  115.  
  116.     maxcyls = fd_tbl->fd_ncyls-1;
  117.     nsects = fd_tbl->fd_sec_per_track;
  118.     nheads = fd_tbl->fd_heads;
  119.     _shprod = nsects * nheads;
  120.     erase_eos(lineno -= 4);
  121.     printf("Maximum cylinder number is %d.\n",maxcyls);
  122.     save_line = lineno+2;
  123.     do {
  124.         erase_eos(lineno = save_line);
  125.         partno = get_scr_char(lineno++,"Add which partition (0 to exit):",'0','4');
  126.         if(partno <'1') {
  127.             return;
  128.             /* NOTREACHED */
  129.         }
  130.         if(part_data[partno -= '1'].sys_ind) {
  131.             scr_pos(13,0);
  132.             message("Partition already active.");
  133.             continue;
  134.             /* NOTREACHED */
  135.         }
  136.         minstart = 0;        /* lowest possible starting cylinder */
  137.         do {
  138.             flag = 0;
  139.             for(i=0; i<4; i++) {
  140.                 PARTDATA ptemp;
  141.                 
  142.                 ptemp = part_data[i];
  143.                 if(    ptemp.sys_ind &&
  144.                     (ptemp.s_cylinder >= minstart && ptemp.s_cylinder-minstart < 3)
  145.                 ) {
  146.                     minstart = ptemp.e_cylinder + 1;
  147.                     flag = 1;
  148.                 }
  149.             }
  150.         } while (flag);
  151.         if(minstart > maxcyls) {
  152.             scr_pos(lineno+1,0);
  153.             message("No room for a new partition on disk.");
  154.             return;
  155.             /* NOTREACHED */
  156.         }
  157.         start = get_scr_val(lineno++,"Enter starting cylinder number:",minstart,minstart,maxcyls-2);
  158.         i = (int) (0xffff/_shprod) + start - 1;
  159.         maxend = min(maxcyls,i);
  160.         do {
  161.             flag = 0;
  162.             for(i=0; i<4; i++)
  163.                 if(part_data[i].sys_ind && part_data[i].e_cylinder == maxend) {
  164.                     maxend = part_data[i].s_cylinder-1;
  165.                     flag = 1;
  166.                 }
  167.         } while (flag);
  168.         if(maxend <= minstart || maxend == -1) {
  169.             scr_pos(lineno+1,0);
  170.             message("No room for partition at selected start position.");
  171.             flag = 1;
  172.             continue;
  173.             /* NOTREACHED */
  174.         }
  175.         end = get_scr_val(lineno++,"Enter ending cylinder number:",maxend,start+2,maxend);
  176. #ifdef DEBUG
  177.     printf("secs_per_track %u, nheads %u ", nsects, nheads);
  178.     printf(" start %d, end %d\n",start,end);
  179.     fflush(stdout);(void) getch();
  180. #endif
  181.         for(i=flag=0; i<4; i++) {
  182.             if(!part_data[i].sys_ind)
  183.                 continue;
  184.             j = part_data[i].s_cylinder;
  185.             k = part_data[i].e_cylinder;
  186.             if(start <= k && end >= j) {
  187.                 flag = 1;    /* blew it on this partition */
  188.                 break;
  189.             }
  190.         }
  191.         if(flag) {
  192.             scr_pos(lineno+1,0);
  193.             message("New partition overlaps an old partition");
  194.         }
  195.     } while (flag);
  196.     part = &master_boot_rec->ptable[partno];
  197.     bptr = &part_boot_rec[partno]->bpb;
  198.     scr_pos(lineno+1,0);
  199.     puts("              1.  Additional DOS Volume");
  200.     puts("              2.  DOS");
  201.     puts("              3.  Extended DOS Partition");
  202.     puts("              4.  XENIX");
  203.     puts("              5.  Other");
  204.     sysno = get_scr_char(lineno,"              0.  Exit                 ",'0','4');
  205.     lineno += 6;
  206.     switch(sysno) {
  207.     case '0':
  208.         return;
  209.         /* NOTREACHED */
  210.     case '4':
  211.         sysno = XENIX_PART;
  212.         break;
  213.     case '1':
  214.         sysno = EDOS_PART;
  215.         break;
  216.     case '2':
  217.         sysno = DOS_PART;
  218.         break;
  219.     case '3':
  220.         sysno = XDOS_PART;
  221.         break;
  222.     case '5':
  223.         sysno = get_scr_val(lineno++,"Enter system ID byte:",0,0,255);
  224.         break;
  225.     }
  226.     bootable = 0;
  227.     if(sysno != EDOS_PART && sysno != XDOS_PART)
  228.         if(get_scr_char(lineno++,"Make this partition bootable? (1=yes)",'0','1') == '1')
  229.             bootable = 1;
  230.     part_data[partno].s_cylinder = start;
  231.     part_data[partno].e_cylinder = end;
  232.     part_data[partno].sys_ind = part->sys_ind = (byte) sysno;
  233.     if(bootable) {
  234.         part->boot_ind = 0x80;
  235.         for(i=0;i<4;i++)
  236.             if (i==partno)
  237.                 continue;
  238.             else
  239.                 if(master_boot_rec->ptable[i].boot_ind) {
  240.                     master_boot_rec->ptable[i].boot_ind = 0;
  241.                     boot_transfer(0,WRITE);
  242.                     break;
  243.                 }
  244.     }
  245.     else
  246.         part->boot_ind = 0;
  247.     part->s_head = 0;
  248.     part->e_head = nheads-1;         /* and end on the last head */
  249.     uns = start ? 1 : 2;    /* if first partition, save extra sec for master boot rec */
  250.     part->s_sec_cyl = put_sec_cyl(uns, start); /* sector 1 */
  251.     part->e_sec_cyl = put_sec_cyl(nsects, end);
  252. #ifdef DEBUG
  253.     printf("\nuns %u, start %d, end %u, nsects %u, s_sec_cyl 0x%x, e_sec_cyl 0x%x\n",
  254.             uns,start,end,nsects,part->s_sec_cyl, part->e_sec_cyl);
  255. #endif
  256.     part->rel_sect = start ? umul1632(start,_shprod) : 1L;
  257.     bptr->bytes_per_sec = sector_size;
  258.     bptr->res_sectors = 1;
  259.     bptr->nfats = 2;
  260.     bptr->media_des = 0xf8;
  261.     uns = (word) (end-start+1) * _shprod; 
  262.     if(!start)    /* adjust for master boot rec */
  263.         uns--;
  264.     bptr->nsectors = uns;
  265.     part->num_sects = (dword) uns;
  266.     if(sysno != EDOS_PART) {
  267.         /* that's it.  write the boot records and return */
  268.         boot_transfer(0,WRITE);
  269.         boot_transfer(partno+1,WRITE);
  270.         scr_pos(lineno+2,0);
  271.         puts("Partition established.  Use appropriate format utility to prep");
  272.         puts("for files.");
  273.         fflush(stdout);
  274.         sleep(5000L);
  275.         return;
  276.         /* NOTREACHED */
  277.     }
  278.     /* make an estimate of parameters to use for number of root entries, fat
  279.      * fat sectors and cluster size to use.  We are somewhat somewhat conservative
  280.      * on the # of fat sectors.
  281.      */
  282.     if(uns <= 2400) {    /* "uns" is # of sectors in partition */
  283.         i = 2;    /* default cluster size */
  284.         bptr->nroot_ents = 0xe0;
  285.     }
  286.     else {
  287.         i = 4;
  288.         bptr->nroot_ents = 0x200;